#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <mutex>
#include <string>
#include "Mutex.hpp"
using namespace MyMutex;

int ticket = 1000;
pthread_mutex_t glock = PTHREAD_MUTEX_INITIALIZER;
// std::mutex cpp_lock;

class ThreadMutex
{
public:
    ThreadMutex(Mutex &lock, const std::string &n) : lockp(&lock), name(n)
    {
    }
    ~ThreadMutex()
    {
    }
    std::string name;
    Mutex *lockp;
};

void *Routine(void *args)
{
    ThreadMutex *td = static_cast<ThreadMutex *>(args);
    while (1)
    {
        { 
            LockGuard guard(*td->lockp);
            // cpp_lock.lock();
            // pthread_mutex_lock(&glock);
            // pthread_mutex_lock(td->lockp);
            if (ticket > 0)
            {
                usleep(1000);
                printf("%s sells ticket:%d\n", td->name.c_str(), ticket);
                ticket--;
                // pthread_mutex_unlock(&glock);
                // pthread_mutex_unlock(td->lockp);
                // cpp_lock.unlock();
            }
            else
            {
                // pthread_mutex_unlock(&glock);
                // pthread_mutex_unlock(td->lockp);
                // cpp_lock.unlock();

                break;
            }
        }
    }
    return nullptr;
}

int main()
{
    pthread_t t1, t2, t3, t4;

    Mutex lock;
    // pthread_mutex_init(&lock, nullptr);
    ThreadMutex *p1 = new ThreadMutex(lock, "thread-1");
    ThreadMutex *p2 = new ThreadMutex(lock, "thread-2");
    ThreadMutex *p3 = new ThreadMutex(lock, "thread-3");
    ThreadMutex *p4 = new ThreadMutex(lock, "thread-4");

    pthread_create(&t1, nullptr, Routine, (void *)p1);
    pthread_create(&t2, nullptr, Routine, (void *)p2);
    pthread_create(&t3, nullptr, Routine, (void *)p3);
    pthread_create(&t4, nullptr, Routine, (void *)p4);

    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);
    pthread_join(t3, nullptr);
    pthread_join(t4, nullptr);
    // pthread_mutex_destroy(&lock);
    return 0;
}